<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ES6 Promise</title>
</head>
<body>
  
</body>
<script>
  function myPromise(executor) {
    let self = this;
    self.status = 'pending';
    self.value = null;
    self.reason = null;

    self.onFulfilledCallbacks = [];
    self.onRejectedCallbacks = [];

    // 成功
    function resolve(value) {
      if (self.status === 'pending') {
        self.value = value; // 保存成功的结果
        self.status = 'fulfilled'; // 修改状态为完成

        self.onFulfilledCallbacks.forEach(item => item(value))
      }
    }

    // 失败
    function reject(reason) {
      if (self.status === 'pending') {
        self.ereasonrror = reason; // 失败原因
        self.status = 'rejected'

        self.onRejectedCallbacks.forEach(item => item(reason))
      }
    }

    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err)
    }
  }


  // 挂载一个全局的then方法
  myPromise.prototype.then = function(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ?
    onFulfilled : function(data) { resolve(data) }

    onRejected = typeof onRejected === 'function' ?
    onRejected : function(err) { throw err }

    let self = this;
    // if (self.status === 'pending') {
    //   self.onFulfilledCallbacks.push(onFulfilled)
    //   self.onRejectedCallbacks.push(onRejected)
    // }

    if (self.status === 'fulfilled') {
      return new myPromise((resolve, reject) => {
        try {
          // 判断传进来的value是不是一个promise
          // 如果是一个promise，则接着.then 否则 resolve出去
          let x = onFulfilled(self.value)
          x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
        } catch (err) {
          reject(err)
        }
      })
    }

    if (self.status === 'rejected') {
      return new myPromise((resolve, reject) => {
        try {
          let x = onRejected(self.error)
          x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
        } catch (err) {
          reject(err)
        }
      })
    }

    if (self.status === 'pending') {
      return new myPromise((resolve, reject) => {
        self.onFulfilledCallbacks.push(() => {
          let x = onFulfilled(self.value)
          x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
        })
        self.onRejectedCallbacks.push(() => {
          let x = onRejected(self.reason)
          x instanceof myPromise ? x.then(resolve, reject) : resolve(x);
        })
      })
    }

  }
  myPromise.prototype.catch = function(fn) {
    return this.then(null, fn)
  }

  // let demo = new myPromise((resolve, reject) => {
  //   console.log('promise success')

  //   setTimeout(() => {
  //     resolve('异步结果返回')
  //   }, 2000)
  // })

  // demo.then(data => console.log(data))

  let isForget = true
  let getLv = new myPromise((resolve, reject) => {
    if (isForget) {
      let lv = {
        color: 'red',
        price: '$99'
      }
      resolve(lv)
    } else {
      let err = new Error('忘记了')
      reject(err)
    }
  })

  let buyLip = (lv) => {
    let lip = {
      brand: 'YSL',
      color: 'red'
    }
    let msg = {
        message: '我买的口红是' + lip.brand + ',搭配我的：' + lv.color,
        lip: lip,
        lv: lv
    }
    
    return new myPromise(function(y, n) {
      y(msg)
    })
  }

  let testFn = () => {
    getLv
      .then(buyLip)
      .then((fulfilled) => {
        console.log(fulfilled)
      }).catch((rejected) => {
        console.log(rejected.message);
      })
  }
  testFn()

</script>
</html>